package cn.xinfei.xdecision.engine.runner.api;

import cn.xinfei.xdecision.common.model.component.ComponentVo;
import cn.xinfei.xdecision.constant.EngineResultEnum;
import cn.xinfei.xdecision.constant.GlobalConstant;
import cn.xinfei.xdecision.engine.runner.context.PipelineContextHolder;
import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.executor.ComponentHandler;
import cn.xinfei.xdecision.engine.runner.executor.DecisionFlowPipeline;
import cn.xinfei.xdecision.engine.runner.executor.ExamHandler;
import cn.xinfei.xdecision.engine.runner.executor.NodeHandler;
import cn.xinfei.xdecision.engine.runner.executor.model.StateTransmitModel;
import cn.xinfei.xdecision.engine.runner.metadata.MetadataProvider;
import cn.xinfei.xdecision.engine.runner.service.ExamNodeService;
import cn.xinfei.xdecision.model.DecisionExamApiResponse;
import cn.xinfei.xdecision.model.DecisionExamComponentApiRequest;
import cn.xinfei.xdecision.model.DecisionExamNodeApiRequest;
import com.dianping.cat.Cat;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

@Slf4j
@Service
public class DecisionExamApi {

    @Autowired
    private MetadataProvider metadataProvider;

    @Autowired
    private ExamNodeService examNodeService;

    public DecisionExamApiResponse executeNode(DecisionExamNodeApiRequest engineApiRequest) {
        Long start = System.currentTimeMillis();
        DecisionExamApiResponse engineApiResponse = new DecisionExamApiResponse();
        String engineCode = engineApiRequest.getEngineCode();
        String businessId = engineApiRequest.getRequestId();
        engineApiResponse.setRequestId(businessId);
        engineApiResponse.setEngineCode(engineCode);

        Map<String, Object> fields = engineApiRequest.getFields();
        PipelineContextHolder.setRequestId(businessId);
        PipelineContextHolder.setDecisionId(businessId);
        PipelineContextHolder.setEngineCode(engineCode);
        PipelineContextHolder.setInvokeRemote(engineApiRequest.isInvokeRemote());
        PipelineContextHolder.setPersistence(engineApiRequest.isPersistence());

        try {

            PipelineContextHolder.putInput(fields);
            MDC.put(GlobalConstant.NID, engineCode);
            String nodeCode = engineApiRequest.getNodeCode();
            Long engineVersionNo = engineApiRequest.getEngineVersionNo();

            Map<String, NodeHandler> engineNodeMap = examNodeService.getNodeInfo(engineCode, engineVersionNo);
            XDecisionContext context = XDecisionContext.getContext();
            context.getPipelineMetaInfoContext().putAll(engineNodeMap);
            NodeHandler nodeHandler = engineNodeMap.get(nodeCode);

            ExamHandler examHandler = new ExamHandler(nodeHandler);

            //2.执行决策流
            StateTransmitModel resultEnum = DecisionFlowPipeline.launch(examHandler);
            Long end = System.currentTimeMillis();
            log.warn("执行成功,engineCode={},nodeCode={}", engineCode, nodeCode);
            engineApiResponse.setEngineResult(EngineResultEnum.SUCCESS_END);
//            engineApiResponse.setOut(resultEnum.getNodeOutput());
            engineApiResponse.setOut(PipelineContextHolder.getOut());
            engineApiResponse.setIn(resultEnum.getNodeInput());
            engineApiResponse.setContext(PipelineContextHolder.getContextValue());
            engineApiResponse.setHitResultList(PipelineContextHolder.getHitResultList());
            engineApiResponse.setRespond(end - start);
            return engineApiResponse;

        } catch (Exception e) {
            log.error("接口请求异常,PENDING,error={}", e.getMessage(), e);
            engineApiResponse.setEngineResult(EngineResultEnum.EXCEPTION_END);
            Cat.logError(e); // 将异常上报到cat上
            return engineApiResponse;
        }
    }

    public DecisionExamApiResponse executeComponent(DecisionExamComponentApiRequest engineApiRequest) {
        Long start = System.currentTimeMillis();
        DecisionExamApiResponse engineApiResponse = new DecisionExamApiResponse();
        String businessId = engineApiRequest.getRequestId();
        engineApiResponse.setRequestId(businessId);

        Map<String, Object> fields = engineApiRequest.getFields();
        PipelineContextHolder.setRequestId(businessId);
        PipelineContextHolder.setDecisionId(businessId);

        PipelineContextHolder.setInvokeRemote(engineApiRequest.isInvokeRemote());
        PipelineContextHolder.setPersistence(engineApiRequest.isPersistence());

        try {

            PipelineContextHolder.putInput(fields);

            ComponentVo componentVo = new ComponentVo();
            String componentCode = engineApiRequest.getComponentCode();
            componentVo.setCode(componentCode);
            componentVo.setVersionNo(engineApiRequest.getComponentVersionNo());
            String nodeType = engineApiRequest.getNodeType();

            ComponentHandler nodeHandler = new ComponentHandler(nodeType, componentVo);
            ExamHandler examHandler = new ExamHandler(nodeHandler);

            //2.执行决策流
            StateTransmitModel resultEnum = DecisionFlowPipeline.launch(examHandler);
            Long end = System.currentTimeMillis();
            log.warn("执行成功,componentCode={}", componentCode);
            engineApiResponse.setEngineResult(resultEnum.getEngineResultEnum());
            engineApiResponse.setOut(resultEnum.getNodeOutput());
            engineApiResponse.setIn(resultEnum.getNodeInput());
            engineApiResponse.setHitResultList(PipelineContextHolder.getHitResultList());
            engineApiResponse.setBranchRejectInfo(PipelineContextHolder.getBranchRejectInfo());
            engineApiResponse.setMsg(resultEnum.getFail());
            engineApiResponse.setRespond(end - start);
            return engineApiResponse;

        } catch (Exception e) {
            log.error("接口请求异常,PENDING,error={}", e.getMessage(), e);
            engineApiResponse.setEngineResult(EngineResultEnum.EXCEPTION_END);
            Cat.logError(e); // 将异常上报到cat上
            return engineApiResponse;
        }
    }
}
